package useRedis

import (
	"errors"
	"fmt"
	"github.com/garyburd/redigo/redis"
	"strconv"
)

type RedisClient struct {
	Host     string
	Port     int
	Db       int
	Password string
	Cli      redis.Conn
}

func (r *RedisClient) Connect() {
	var address = fmt.Sprintf("%s:%d", r.Host, r.Port)
	db := redis.DialDatabase(r.Db)
	password := redis.DialPassword(r.Password)

	cli, e := redis.Dial("tcp", address, db, password)
	if e != nil {
		fmt.Println(e.Error())
		return
	}
	r.Cli = cli
}

func (r *RedisClient) Get(key string) (interface{}, error) {
	s, e := r.Cli.Do("GET", key)
	if e != nil {
		fmt.Println(e.Error())
		return nil, e
	}
	return s, nil
}

func (r *RedisClient) GetStr(key string) (string, error) {
	s, e := r.Cli.Do("GET", key)
	if e != nil {
		fmt.Println(e.Error())
		return "", e
	}

	switch s := s.(type) {
	case string:
		return s, nil
	case []byte:
		return string(s), nil
	default:
		return "", errors.New("Not String")
	}
}

func (r *RedisClient) GetInt(key string) (int, error) {
	s, e := r.Cli.Do("GET", key)
	if e != nil {
		fmt.Println(e.Error())
		return 0, e
	}
	switch s := s.(type) {
	case int:
		return s, nil
	case []byte:
		v, _ := strconv.Atoi(string(s))
		return v, nil
	default:
		return 0, errors.New("Not Int")
	}
}

func (r *RedisClient) Set(key string, value interface{}) bool {
	_, e := r.Cli.Do("SET", key, value)
	return e == nil
}

func (r *RedisClient) SetEx(key string, value interface{}, ex int) bool {
	_, e := r.Cli.Do("SET", key, value, "EX", ex)
	return e == nil
}

func (r *RedisClient) SetHash(key string, field string, value string) bool {
	_, e := r.Cli.Do("HSET", key, field, value)

	return e == nil
}

func (r *RedisClient) GetHash(key string, field string) (string, error) {
	v, e := r.Cli.Do("HGET", key, field)
	if e != nil {
		return "", e
	}

	switch v := v.(type) {
	case []byte:
		return string(v), nil
	case string:
		return v, nil
	default:
		return "", errors.New("UnKnown Type of value")
	}
}

func (r *RedisClient) DelHashField(key string, field string) bool {
	_, e := r.Cli.Do("HDEL", key, field)
	return e == nil
}

func (r *RedisClient) DelKey(key string) bool {
	_, e := r.Cli.Do("DEL", key)
	return e == nil
}

func (r *RedisClient) LPush(key string, value ...string) bool {
	_, e := r.Cli.Do("LPUSH", key, value)
	return e == nil
}

func (r *RedisClient) RPush(key string, value ...string) bool {
	_, e := r.Cli.Do("RPUSH", key, value)
	return e == nil
}
func (r *RedisClient) LPop(key string, value ...string) (string, error) {
	v, e := r.Cli.Do("LPOP", key, value)
	if e != nil {
		return "", e
	}
	return ToString(v), nil
}

func (r *RedisClient) RPop(key string, value ...string) (string, error) {
	v, e := r.Cli.Do("RPOP", key, value)
	if e != nil {
		return "", e
	}
	return ToString(v), nil
}

func ToString(value interface{}) string {
	switch value := value.(type) {
	case []byte:
		return string(value)
	case string:
		return value
	default:
		return ""
	}
}
